#pragma once

#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>
#include "Socket.hpp"

namespace TcpServerModule
{
    using namespace SocketModule;
    using tcphandler_t = std::function<bool(SockPtr, InetAddr)>;

    //tcpserver它只负责IO, 流式的IO, 不对协议进行任何处理
    class TcpServer
    {
    public:
        TcpServer(int port)
            : _port(port)
            , _listensockp(std::make_unique<TcpSocket>()) //对象
            , _isrunning(false)
        {}

        //设置handler, 进行tcp套接字创建套路
        void InitServer(tcphandler_t handler)
        {
            _handler = handler;
            _listensockp->BuildTcpSocketMethod(_port);
        }

        //执行方法, IO操作
        void Loop()
        {   
            _isrunning = true;
            while(_isrunning)
            {
                //1.accept 获取新连接
                //进行下层方法的调用, 返回一个真正的套接字
                InetAddr clientaddr;
                auto sockfd = _listensockp->Accepter(&clientaddr);  
                if(sockfd == nullptr)
                    continue;
                //2.IO处理
                LOG(LogLevel::DEBUG) << "get a new client, info is:" << clientaddr.Addr();

                //子进程进行任务处理
                pid_t id = fork();
                if(id == 0)
                {
                    _listensockp->Close(); //关闭不需要的文件描述符监听
                    if(fork() > 0)
                        exit(0);
                    _handler(sockfd, clientaddr);
                    exit(0);
                }
                sockfd->Close();
                waitpid(id, nullptr, 0); //如果子进程退出了, 这里就不会阻塞等待了
            }
            _isrunning = false;
        }
        ~TcpServer()
        {
            _listensockp->Close();
        }

    private:
        //一定要有一个Listensock
        std::unique_ptr<Socket> _listensockp;
        bool _isrunning; //服务器是否启动
        int _port; //端口号
        tcphandler_t _handler; //需要执行的上层调用的方法, 本层只做IO操作
    };
}